#include "HIRCode.h"

HSymbolTable * HSymbolTable::root = nullptr;

// Add a child and return its pointer
HSymbolTable* HSymbolTable::add_child()
{
	HSymbolTable *pct = new HSymbolTable(this);
	_children.push_back(pct);
	return pct;
}

/*
 * Add a symbol to the table and return its index,
 * or `SIZE_MAX` if the symbol already exists.
 */
size_t HSymbolTable::add_symbol(const std::string &id, const cact_type_t *type)
{
	size_t idx = _symbols.size();
	HSTEntry symbol;
	HSymbolTable *psymtb;

	if (search_symbol(id, psymtb, 0) != SIZE_MAX)
		// symbol already exists
		return SIZE_MAX;
	symbol.id = id;
	symbol.type = type;
	symbol.latn = symbol.pttn = INVALID_TEMP_NO;
	_symbols.push_back(symbol);
	return idx;
}

/*
 * Search the symbol table and return the index
 * or `SIZE_MAX` if not found.
 * Pointer to the symbol table containing the symbol would be returned in `psymtb`.
 * If `recur` is not `0`, the search would continue to its parent until the root.
 * Otherwise, it only search the symbol in current table.
 */
size_t HSymbolTable::search_symbol(const std::string &id,
	HSymbolTable * &psymtb, int recur) const
{
	for (size_t i = 0u; i < _symbols.size(); ++i)
		if (_symbols.at(i).id == id)
		{
			psymtb = const_cast<HSymbolTable *>(this);
			return i;
		}
	if (recur == 0 || _parent == nullptr)
		return SIZE_MAX;
	else
		return _parent->search_symbol(id, psymtb, 1);
}